package ua.kpi.fpm.km61.strat.sp.util;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

import ua.kpi.fpm.km61.strat.sp.rules.Chain;
import ua.kpi.fpm.km61.strat.sp.rules.GramSymbol;
import ua.kpi.fpm.km61.strat.sp.rules.NonTerminal;
import ua.kpi.fpm.km61.strat.sp.rules.Rule;
import ua.kpi.fpm.km61.strat.sp.rules.Terminal;

public class FileProcessor {
	
	private final static String TERMINALSFILE = "terminals.txt";
	
	private final static String RULESFILE = "rules.txt";

	public static List<Rule> parseRules(Set<Terminal> terminals) {
		List<Rule> rules = new ArrayList<Rule>();
		if (RULESFILE != null) {
			try {
				FileReader fr = new FileReader(RULESFILE);
				BufferedReader br = new BufferedReader(fr);
				rules.addAll(FileProcessor.splite(br, terminals));
				br.close();
				fr.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return rules;
	}

	private static List<Rule> splite(BufferedReader br, Set<Terminal> terminals) throws IOException {
		List<Rule> rules = new ArrayList<Rule>();
		if (br != null) {
			String tmp = "";
			int i = 1;
			while ((tmp = br.readLine()) != null) {
				NonTerminal inSymbol = new NonTerminal();
				inSymbol.setName(tmp.substring(0, tmp.indexOf("::=")-1));
				String out = tmp.substring(tmp.indexOf("::=") + 4);
				Chain chain = FileProcessor.getRight(out, terminals);
				Rule rule = new Rule(inSymbol, chain);
				rules.add(rule);
				i++;
			}
		}
		return rules;
	}
	
	private static Chain getRight(String out, Set<Terminal> terminals){
		Chain chain = new Chain();
		Scanner scan = new Scanner(out);
		scan.useDelimiter(" ");
		List<GramSymbol> outSymbols = new ArrayList<GramSymbol>();
		while (scan.hasNext()) {
			String name = scan.next();
			GramSymbol term = new Terminal(name);
			if(terminals.contains(term)){
				outSymbols.add(term);
			} else {
				NonTerminal s = new NonTerminal();
				s.setName(name);
				outSymbols.add(s);
			}
		}
		chain.setOut(outSymbols);
		return chain;
	}

	public static Set<Terminal> parseTerminals() {
		Set<Terminal> terminals = new HashSet<Terminal>();
		if (TERMINALSFILE != null) {
			try {
				FileReader fr = new FileReader(TERMINALSFILE);
				BufferedReader br = new BufferedReader(fr);
				terminals.addAll(FileProcessor.scanTerminal(br));
				br.close();
				fr.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return terminals;
	}

	private static Set<Terminal> scanTerminal(BufferedReader br) throws IOException {
		Set<Terminal> terminals = new HashSet<Terminal>();
		if (br != null) {
			String tmp = "";
			while ((tmp = br.readLine()) != null) {	
				Terminal terminal = new Terminal(tmp);
				terminals.add(terminal);
			}
		}
		return terminals;
	}
}